1 Introduction

We covered one-way ANOVA, randomized block design, and multifactorial design. As you may have already figured, we started with simple experimental designs, and gradually move towards more complex experimental designs.

This time, we will cover experimental designs involving repeated measures. We will cover

  1. Why is repeated measure a problem for ANOVA?
  2. What is a random effect?
  3. How to set up a mixed effect model?
  4. How to analyze a mixed effect model?

2 Load packages

library(lme4)
library(lmerTest)   #two new packages


library(emmeans)  
library(multcomp)
library(multcompView)
library(ggplot2) 
library(tidyr)
library(dplyr)
library(readr)
library(readxl)
library(RColorBrewer)
library(viridis)

3 Why is repeated measure a problem for ANOVA

Repeated measures refer to the fact that in some experiments, the same entity is measured multiple times. How could that be?

Let’s imagine an experiment like this:

Say I am tracking the heights of some rice plants over time. Every week, I go to measure the height of those plants.

And THAT is a kind of repeated measure. The same plants are measured multiple times throughout the experiment. Whenever the same entity is measured multiple times (either across time or space), it is a repeated measures experiment.

Let’s go over another example. Say I am interested in the number of seeds per plant across two genotypes of rice. There are three pots per genotype, and three plants per pot. (All three plants in a pot are the same genotype.) Then I count the number of seeds in each plant.
And THAT is a repeated measure. The pots are being repeatedly measured for the plants in them. And the pots cannot be used as a blocking factor, because there is only one genotype per pot.

But why is that a problem? Remember, the assumption of ANOVA is that each observation is independent of the other. And repeated measures is a violation of that assumption. When multiple measurements of the same entity were taken, those measurements will NOT be independent of each other, because they are all affected by the same entity.

Repeated measures always reduce the number of independent observations you have, and one must correct for repeated measures.

4 Working with repeated measures - using random effects

To correct for repeated measures, we need to declare the entities that are repeatedly measured as “random effects”.

This is a very abstract concept. So the best way to explain is to use an example.

We are comparing the height of two rice genotypes, WT and mutant, through time. Every week we measure the heights of those plants. (Data from Sundaresan Lab, Department Of Plant Biology, UC Davis)

rice_growth <- read_csv("https://raw.githubusercontent.com/johnshorter/TeachingData/refs/heads/main/rice_growth_data.csv")
head(rice_growth)

In this experiment, each pot was randomly assigned a genotype, either WT or mutant. The mutant is called “48/48”. There was one plant per pot. The total of 48 pots were randomly placed into 6 flats, and 8 pots per flat. So the flat was a blocking factor. We measure the height every week, starting from week 3 to week 9, (but not week 8), so total of 6 time points.

Before we talk about random effects, we need to talk about fixed effects. Simply put, the fixed effects are your treatments. In this example, We have two fixed effects: genotype and age.

Let’s look at all the factors in this experiment

sources factor levels
time treat 6
genot treat 2
flat block 6
pot EU 48

Because there are two independent variables (time and genotype) and one blocking factor, this experiment will be called a randomized block multifactorial design.

Note In this example, plant or pot is the experimental unit for genotype, because the treatment of genotype was applied to each pot, and there is only one plant in each pot. Note Pot is also the entity that has been repeatedly measured through weeks.

You might ask, then where is the observational unit? The OU is actual the plant at each week, or the plant:week combination.

Coming back to random effects. What is a random effect?

  1. A random effect CANNOT be a treatment (because they are fixed effects);
  2. An EU that is not an OU must be declared as a random effect;
  3. An entity that is repeatedly measured must be declared as a random effect;
  4. Blocking factors can be declared as random effects, but they don’t have to.

So in this example, what needs to be declared as a random effect? The pot needs to be declared as a random effect, since it is both the EU for genotype and the entity of repeated measures.

5 Setting up a mixed effect model

A mixed effect model refers to a model that contains both fixed effects and random effects. A mixed effect model is appropriate for this experiment, because we have two fixed effects (time and genotype) and one random effect (pot). #### note, pot is the covariate within which we have repeated measures

How do I set up the model? To set up the mixed effect model, we will need a new function. Instead of lm(), we will use lmer(). This will be the command for mixed effect linear model.

To specify a random effect, we’ll use the (1|random_effect) syntax. In this example, it will be (1|pot)

In the model, you will put in your fixed effect and interactions first, then you put in blocking factors, then you put in random effects. So the model will be lmer(height ~ time + genotype + time:genotype + flat + (1|pot)) You can also do time*genotype + flat + (1|pot). That gives you the same thing.

Do not include the interactions with blocking factors (flat). The blocking factor only exists to control for unintended variations. And we are not interested in the flat:time or flat:genotype effects.

You might ask can I do height ~ genotype * time + flat + (1|plant)? In an experiment like this,
you should put the non-manipulative factor (time) first,
then you put the manipulative factor (genotype) second.

The reason is that in a mixed effect model, the first factor in the model will account for variation first; then the rest of the variation will be passed on to the second factor in the model, and so on.

By common sense, we know plants grow taller over time. So we expect that time explains more variation than genotype. So we will put time first in the model.

You can also declare the flat as a random effect by using (1|flat). Either way is correct, but setting the flat as a random effect is more conservative, meaning you’ll need a larger difference in mean to detect a significant difference

Last thing: before you set up the model, is there any numeric variables that you need to change to factors?

rice_growth <- rice_growth %>% 
  mutate(age.f = factor(age_weeks)) %>% 
  mutate(flat.f = factor(flat)) 
model_rice <- lmer(Height_mm ~ age.f * genotype + (1|flat.f) + (1|pot), data = rice_growth)

6 Data visualization

Before we do any analysis, let’s plot the data and look at it first. Plot age.f on x axis, and Height_mm on y axis. Color by genotype.

Make the best plot you can here:

wisteria <- c("grey65", "burlywood3", "khaki2", "plum1", "lightcyan2", "cornflowerblue", "slateblue3")

rice_growth %>% 
  ggplot(aes(x = age_weeks, y = Height_mm)) +
  stat_summary(geom = "line",  
               fun = mean,  
               aes(group = genotype, color = genotype),  
               size = 1.2) + 
  stat_summary(geom = "ribbon",   
               fun.data = mean_se, 
               aes(group = genotype,
                   fill = genotype), 
               alpha = 0.5) +   
  geom_point(aes(fill = genotype), 
             position = position_jitter(0.1, seed = 666),    
             alpha = 0.8,             
             size = 3,
             shape = 21, 
             color = "black") +    
  scale_fill_manual(values = wisteria[c(1, 7)]) +  
  scale_color_manual(values = wisteria[c(1, 7)]) + 
  scale_x_continuous(breaks = c(3, 4, 5, 6, 7, 9)) +  
  labs(x = "Age (weeks)",              
       y = "Height mm",
       fill = "genotype",
       color = "genotype") +
  guides(color = "none") +
  guides(fill = guide_legend(nrow = 1, ncol = 2)) + # set fill legend to 1 row 2 columns. 
  theme_minimal() +
  theme(legend.position = c(0.8, 0.15),
        axis.line = element_line(size = 1.2), 
        text = element_text(size = 12, color = "black", face = "bold"),
        axis.text = element_text(size = 12, color = "black", face = "bold")
        )

We can also pull out the summary statistics. We’ll need to group by genotype and age.f

rice_growth %>% 
  group_by(genotype, age.f) %>% 
  summarise(mean = mean(Height_mm),
            var = var(Height_mm),
            sd = sd(Height_mm),
            n = n()) 

The variances seem to increase as the means increase, but I don’t think it’s too bad (not orders of magnitude different). If you are interested, you can try a log transformation and compare results. I think the conclusions should practically be the same.

7 Stats

We have our model, now let’s check the assumptions of ANOVA first.

Normality? It turns out the plot(model, which = 2) command wouldn’t work on mixed effect models. We will use qqnorm(resid(model)) instead. The resid() function pull out all the residues in a model.

qqnorm(resid(model_rice))

Pretty normally distributed.

Equal variance across groups?

plot(model_rice)

It turns out when you call plot() on a mixed effect model, it gives you the residue vs. mean plot. The residues seem to be pretty evenly spread across the range of mean. The variances are more or less even across groups, although there is a slightly larger spread at the high end of the data.

So now we are all clear to do ANOVA.

7.1 ANOVA

anova(model_rice)
Type III Analysis of Variance Table with Satterthwaite's method
                 Sum Sq Mean Sq NumDF   DenDF   F value    Pr(>F)    
age.f          16398687 3279737     5 230.000 4578.6270 < 2.2e-16 ***
genotype          16523   16523     1  41.323   23.0673 2.078e-05 ***
age.f:genotype    18386    3677     5 230.000    5.1336 0.0001747 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Not surprisingly, age.f explain the most variation in the data (F = 4578)! Genotype also explains a significant amount of variation in the dataset (F = 23 >> 1). The interaction between the treatments are also significant (F = 5 > 1).

7.2 Tukey test

Let’s really not a question of whether or not the height is different across age, because we know plants grow taller over time. The real question is whether or not WT is taller or shorter than the mutant across age.

So the emmeans layout should be ~ genotype | age.f

estimate_rice <- emmeans(model_rice, pairwise ~ genotype | age.f)
estimate_rice$contrast
age.f = 3:
 contrast     estimate   SE  df t.ratio p.value
 (48/48) - WT    -21.0 10.8 119  -1.949  0.0536

age.f = 4:
 contrast     estimate   SE  df t.ratio p.value
 (48/48) - WT    -31.6 10.8 119  -2.929  0.0041

age.f = 5:
 contrast     estimate   SE  df t.ratio p.value
 (48/48) - WT    -68.6 10.8 119  -6.368 <0.0001

age.f = 6:
 contrast     estimate   SE  df t.ratio p.value
 (48/48) - WT    -51.2 10.8 119  -4.755 <0.0001

age.f = 7:
 contrast     estimate   SE  df t.ratio p.value
 (48/48) - WT    -31.5 10.8 119  -2.921  0.0042

age.f = 9:
 contrast     estimate   SE  df t.ratio p.value
 (48/48) - WT    -28.3 10.8 119  -2.629  0.0097

Degrees-of-freedom method: satterthwaite 

You can also look at cld if you like.

cld(estimate_rice$emmeans, Letters = letters)
age.f = 3:
 genotype emmean   SE   df lower.CL upper.CL .group
 48/48        92 14.0 9.18     60.3      124  a    
 WT          113 13.3 7.49     81.9      144  a    

age.f = 4:
 genotype emmean   SE   df lower.CL upper.CL .group
 48/48       200 14.0 9.18    167.9      231  a    
 WT          231 13.3 7.49    200.0      262   b   

age.f = 5:
 genotype emmean   SE   df lower.CL upper.CL .group
 48/48       328 14.0 9.18    296.2      359  a    
 WT          396 13.3 7.49    365.3      428   b   

age.f = 6:
 genotype emmean   SE   df lower.CL upper.CL .group
 48/48       498 14.0 9.18    466.0      529  a    
 WT          549 13.3 7.49    517.8      580   b   

age.f = 7:
 genotype emmean   SE   df lower.CL upper.CL .group
 48/48       646 14.0 9.18    614.2      677  a    
 WT          677 13.3 7.49    646.2      708   b   

age.f = 9:
 genotype emmean   SE   df lower.CL upper.CL .group
 48/48       779 14.0 9.18    747.7      811  a    
 WT          808 13.3 7.49    776.5      839   b   

Degrees-of-freedom method: satterthwaite 
Confidence level used: 0.95 
significance level used: alpha = 0.05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 

What does this tell us? It tells us that in each time point (except the first), WT plants are on average significantly taller than 48/48 plants.

(Note: The differences in heights at week 9 is 28.3 mm. In reality, ~30 mm (3cm) difference in height is practically nothing for rice plants. Even though something is statistically significant, it does not always mean something practically different.)

8 Exercise

Now you have learned how to deal with repeated measures in an experiment, it’s time for you to practice.

We will use a mint growth experiment as an example. In this experiment, the researchers looked at the effect of 6 treatments (A - F) on mint growth. Each treatment has 3 pots. Each pot has 4 plants. The treatment was applied to the pot, not the individual plants. The growth of each plant in each pot was measured. (Data from UC Davis Plant Sciences course PLS205, Winter 2017)

mint_data <- read_csv("https://raw.githubusercontent.com/johnshorter/TeachingData/refs/heads/main/Mint.csv")
head(mint_data)
tail(mint_data)

There is a problem with how the data were recorded. Maybe it’s not obvious to you. In each treatment, the name of the Pot is all Pot_1, Pot_2 and Pot_3. However, in the actual experiment, Pot_1 from Treatment A is not the same Pot_1 for Treatment B, or CDEF. The same applies to Pot_2 and Pot_3. Simply put, the pots in each treatment need to have their own unique identifier. Let’s fix that first.

mint_data <- mint_data %>% 
  mutate(Pot.ID = paste(Pot, Trtmt))

head(mint_data)
mint_data %>% 
  group_by(Trtmt) %>% 
  summarise(mean = mean(Growth),
            var = var(Growth),
            sd = sd(Growth),
            n = n()) 

Now each pot has their own unique ID. Pot is the EU that has multiple measurements.

8.1 Visualization

Make the best plot you can to visualize the data.

What to put on x axis? What to color/fill with? Any faceting that you want to use?

Make your plot here:

mint_data %>% 
  mutate(Plant = factor(Plant)) %>% 
  ggplot(aes(x = Trtmt, y = Growth)) +
  geom_point(aes(fill = Plant), 
             position = position_jitter(0.1, seed = 666),    
             alpha = 0.8,             
             size = 3,
             shape = 21, 
             color = "black") +    
  scale_fill_manual(values = wisteria[c(1,2,3, 7)]) +  
  scale_color_manual(values = wisteria[c(1,2,3, 7)]) + 
  #scale_x_continuous(breaks = c(3, 4, 5, 6, 7, 9)) +  
  labs(x = "Treatment",              
       y = "Growth",
       fill = "Plant",
       color = "Plant") +
  guides(color = "none") +
  #guides(fill = guide_legend(nrow = 1, ncol = 2)) + # set fill legend to 1 row 2 columns. 
  theme_minimal() +
  theme(legend.position = "bottom",
        axis.line = element_line(size = 1.2), 
        text = element_text(size = 12, color = "black", face = "bold"),
        axis.text = element_text(size = 12, color = "black", face = "bold")
        )

8.2 What is being repeatedly measured in this experiment?

Can you tell which entity was repeatably measured?

Fill in the table and write down the model. What are the sources of variation? What factors are they? (treatment? block? observational units? experimental units?) How many levels in each?

What is the experimental unit for treatment? What is the observational unit?

sources factor levels
Trmt treat 6
Pot.ID EU 18
Pot.ID.Plant OU 72

Technically plant could be a blocking factor if there was something systematic about it e.g. coming from a certain seed container or whatever, but in this we know nothing, it’s just a number, and doesn’t seem to affect the treatments from visualizing the data.

Set up the linear model.

8.3 Check assumptions of ANOVA

model_mint <- lmer(Growth ~ Trtmt + (1|Pot.ID), data = mint_data) # random intercept for Pot.ID
qqnorm(resid(model_rice))

plot(model_mint)

Normality?

Equal variance?

8.4 Run ANOVA

How would you interpret the ANOVA table?

anova(model_mint)
Type III Analysis of Variance Table with Satterthwaite's method
      Sum Sq Mean Sq NumDF DenDF F value    Pr(>F)    
Trtmt 77.942  15.588     5    12  16.689 4.881e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

F value significant, means of treatment groups are different.

8.5 Tukey test

Pull out the cld output and interpret the results.

estimate_mint <- emmeans(model_mint, pairwise ~ Trtmt)
estimate_mint$contrast
 contrast          estimate    SE df t.ratio p.value
 Trtmt_A - Trtmt_B   -0.458 0.599 12  -0.765  0.9685
 Trtmt_A - Trtmt_C   -1.542 0.599 12  -2.574  0.1776
 Trtmt_A - Trtmt_D   -3.667 0.599 12  -6.121  0.0006
 Trtmt_A - Trtmt_E   -2.792 0.599 12  -4.661  0.0056
 Trtmt_A - Trtmt_F   -4.250 0.599 12  -7.095  0.0001
 Trtmt_B - Trtmt_C   -1.083 0.599 12  -1.809  0.4954
 Trtmt_B - Trtmt_D   -3.208 0.599 12  -5.356  0.0018
 Trtmt_B - Trtmt_E   -2.333 0.599 12  -3.895  0.0202
 Trtmt_B - Trtmt_F   -3.792 0.599 12  -6.330  0.0004
 Trtmt_C - Trtmt_D   -2.125 0.599 12  -3.548  0.0364
 Trtmt_C - Trtmt_E   -1.250 0.599 12  -2.087  0.3542
 Trtmt_C - Trtmt_F   -2.708 0.599 12  -4.521  0.0071
 Trtmt_D - Trtmt_E    0.875 0.599 12   1.461  0.6929
 Trtmt_D - Trtmt_F   -0.583 0.599 12  -0.974  0.9178
 Trtmt_E - Trtmt_F   -1.458 0.599 12  -2.435  0.2187

Degrees-of-freedom method: kenward-roger 
P value adjustment: tukey method for comparing a family of 6 estimates 
cld(estimate_mint, Letters = letters)
 Trtmt   emmean    SE df lower.CL upper.CL .group
 Trtmt_A   3.67 0.424 12     2.74     4.59  a    
 Trtmt_B   4.12 0.424 12     3.20     5.05  a    
 Trtmt_C   5.21 0.424 12     4.29     6.13  ab   
 Trtmt_E   6.46 0.424 12     5.54     7.38   bc  
 Trtmt_D   7.33 0.424 12     6.41     8.26    c  
 Trtmt_F   7.92 0.424 12     6.99     8.84    c  

Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 
P value adjustment: tukey method for comparing a family of 6 estimates 
significance level used: alpha = 0.05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 

Treatment F has the highest estimate but is not significantly different from E and D

8.6 What to submit to Moodle (Pass/Fail)

For this lesson, complete the exercises in your shared Exercise Pack (the file Exercise_Pack_Template.Rmd). Then Knit to HTML and upload the HTML file to the Moodle exercise folder.

File name format: Lastname_Firstname_L11.html

8.6.1 Satisfactory / Not satisfactory (what I check)

Your submission is Satisfactory if:

  • It knits (HTML opens and shows your work).
  • You included outputs (plots/tables/model output) that match the lesson.
  • You answered the Self-check checklist (short, honest, and complete).
  • Your work is plausible (right method for the lesson, correct variables, no obvious copy/paste without results).

If one or more of these are missing, it is Not satisfactory (and you resubmit). ## Additional exercises (complete these in your Exercise Pack)

8.6.2 Exercise 2 — Random intercept model

Fit a mixed model with a random intercept for subject (or repeated unit). Compare it to a model without the random effect.

avg_mint <- mint_data %>% split(mint_data$Pot.ID) %>% lapply(function(x){
  avg.growth <- mean(x$Growth)
  unique.vars <- x %>% dplyr::select(c(Trtmt, Pot.ID)) %>% unique()
  unique.vars %<>% mutate(avg_growth = avg.growth)
  return(unique.vars)
}) %>% bind_rows()

model_mint_avg <- lm(avg_growth ~ Trtmt, data = avg_mint)
plot(model_mint_avg)

anova(model_mint_avg)
Analysis of Variance Table

Response: avg_growth
          Df Sum Sq Mean Sq F value    Pr(>F)    
Trtmt      5 44.911  8.9821  16.689 4.881e-05 ***
Residuals 12  6.458  0.5382                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
estimate_mint_avg <- emmeans(model_mint_avg, pairwise ~ Trtmt)
estimate_mint_avg$contrast
 contrast          estimate    SE df t.ratio p.value
 Trtmt_A - Trtmt_B   -0.458 0.599 12  -0.765  0.9685
 Trtmt_A - Trtmt_C   -1.542 0.599 12  -2.574  0.1776
 Trtmt_A - Trtmt_D   -3.667 0.599 12  -6.121  0.0006
 Trtmt_A - Trtmt_E   -2.792 0.599 12  -4.661  0.0056
 Trtmt_A - Trtmt_F   -4.250 0.599 12  -7.095  0.0001
 Trtmt_B - Trtmt_C   -1.083 0.599 12  -1.809  0.4954
 Trtmt_B - Trtmt_D   -3.208 0.599 12  -5.356  0.0018
 Trtmt_B - Trtmt_E   -2.333 0.599 12  -3.895  0.0202
 Trtmt_B - Trtmt_F   -3.792 0.599 12  -6.330  0.0004
 Trtmt_C - Trtmt_D   -2.125 0.599 12  -3.548  0.0364
 Trtmt_C - Trtmt_E   -1.250 0.599 12  -2.087  0.3542
 Trtmt_C - Trtmt_F   -2.708 0.599 12  -4.521  0.0071
 Trtmt_D - Trtmt_E    0.875 0.599 12   1.461  0.6929
 Trtmt_D - Trtmt_F   -0.583 0.599 12  -0.974  0.9178
 Trtmt_E - Trtmt_F   -1.458 0.599 12  -2.435  0.2187

P value adjustment: tukey method for comparing a family of 6 estimates 
cld(estimate_mint_avg, Letters = letters)
 Trtmt   emmean    SE df lower.CL upper.CL .group
 Trtmt_A   3.67 0.424 12     2.74     4.59  a    
 Trtmt_B   4.12 0.424 12     3.20     5.05  a    
 Trtmt_C   5.21 0.424 12     4.29     6.13  ab   
 Trtmt_E   6.46 0.424 12     5.54     7.38   bc  
 Trtmt_D   7.33 0.424 12     6.41     8.26    c  
 Trtmt_F   7.92 0.424 12     6.99     8.84    c  

Confidence level used: 0.95 
P value adjustment: tukey method for comparing a family of 6 estimates 
significance level used: alpha = 0.05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 

Interestingly we get the exact same results. It turns out that with a balanced dataset the mixed model reduces to averaging by the repeated measurement covariates.

Self-check: you show both models and a short justification for the random effect.

8.6.3 Exercise 3 — Trajectory plot

Make a plot showing repeated measurements over time (or condition) per subject.

Self-check: each subject has multiple points; patterns are visible.

8.6.4 Exercise 4 — Assumptions and residuals

Check residual diagnostics for the mixed model and state one limitation.

Self-check: at least one diagnostic plot + one limitation statement.

8.6.5 Exercise 5 — Mini-transfer

Apply a mixed model idea to a different dataset (built-in or from the lesson) with a sensible random effect.

Self-check: you clearly identify what is the repeated/clustered unit.

LS0tCnRpdGxlOiAiMTEgLSBSZXBlYXRlZCBtZWFzdXJlcyBhbmQgbWl4ZWQgZWZmZWN0IG1vZGVscyIKYXV0aG9yOiAiSm9obiBTaG9ydGVyIgpkYXRlOiAiMTkvRGVjLzIwMjYiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMgIAogIGh0bWxfbm90ZWJvb2s6ICAgCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcyAgICAKICAgIHRvYzogeWVzICAKICAgIHRvY19mbG9hdDogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobWFncml0dHIpCmBgYAoKIyBJbnRyb2R1Y3Rpb24KCldlIGNvdmVyZWQgb25lLXdheSBBTk9WQSwgcmFuZG9taXplZCBibG9jayBkZXNpZ24sIGFuZCBtdWx0aWZhY3RvcmlhbCBkZXNpZ24uCkFzIHlvdSBtYXkgaGF2ZSBhbHJlYWR5IGZpZ3VyZWQsIHdlIHN0YXJ0ZWQgd2l0aCBzaW1wbGUgZXhwZXJpbWVudGFsIGRlc2lnbnMsCmFuZCBncmFkdWFsbHkgbW92ZSB0b3dhcmRzIG1vcmUgY29tcGxleCBleHBlcmltZW50YWwgZGVzaWducy4KClRoaXMgdGltZSwgd2Ugd2lsbCBjb3ZlciBleHBlcmltZW50YWwgZGVzaWducyBpbnZvbHZpbmcgcmVwZWF0ZWQgbWVhc3VyZXMuIFdlIHdpbGwgY292ZXIKCjEuICBXaHkgaXMgcmVwZWF0ZWQgbWVhc3VyZSBhIHByb2JsZW0gZm9yIEFOT1ZBPwoyLiAgV2hhdCBpcyBhIHJhbmRvbSBlZmZlY3Q/CjMuICBIb3cgdG8gc2V0IHVwIGEgbWl4ZWQgZWZmZWN0IG1vZGVsPwo0LiAgSG93IHRvIGFuYWx5emUgYSBtaXhlZCBlZmZlY3QgbW9kZWw/CgojIExvYWQgcGFja2FnZXMKCmBgYHtyfQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkobG1lclRlc3QpICAgI3R3byBuZXcgcGFja2FnZXMKCgpsaWJyYXJ5KGVtbWVhbnMpICAKbGlicmFyeShtdWx0Y29tcCkKbGlicmFyeShtdWx0Y29tcFZpZXcpCmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeSh2aXJpZGlzKQpgYGAKCiMgV2h5IGlzIHJlcGVhdGVkIG1lYXN1cmUgYSBwcm9ibGVtIGZvciBBTk9WQQoKUmVwZWF0ZWQgbWVhc3VyZXMgcmVmZXIgdG8gdGhlIGZhY3QgdGhhdCBpbiBzb21lIGV4cGVyaW1lbnRzLCB0aGUgc2FtZSBlbnRpdHkgaXMgbWVhc3VyZWQgbXVsdGlwbGUgdGltZXMuCkhvdyBjb3VsZCB0aGF0IGJlPwoKTGV0J3MgaW1hZ2luZSBhbiBleHBlcmltZW50IGxpa2UgdGhpczoKClNheSBJIGFtIHRyYWNraW5nIHRoZSBoZWlnaHRzIG9mIHNvbWUgcmljZSBwbGFudHMgb3ZlciB0aW1lLgpFdmVyeSB3ZWVrLCBJIGdvIHRvIG1lYXN1cmUgdGhlIGhlaWdodCBvZiB0aG9zZSBwbGFudHMuCgpBbmQgKlRIQVQqIGlzIGEga2luZCBvZiByZXBlYXRlZCBtZWFzdXJlLiBUaGUgc2FtZSBwbGFudHMgYXJlIG1lYXN1cmVkIG11bHRpcGxlIHRpbWVzIHRocm91Z2hvdXQgdGhlIGV4cGVyaW1lbnQuCldoZW5ldmVyIHRoZSBzYW1lIGVudGl0eSBpcyBtZWFzdXJlZCBtdWx0aXBsZSB0aW1lcyAoZWl0aGVyIGFjcm9zcyB0aW1lIG9yIHNwYWNlKSwKaXQgaXMgYSByZXBlYXRlZCBtZWFzdXJlcyBleHBlcmltZW50LgoKTGV0J3MgZ28gb3ZlciBhbm90aGVyIGV4YW1wbGUuClNheSBJIGFtIGludGVyZXN0ZWQgaW4gdGhlIG51bWJlciBvZiBzZWVkcyBwZXIgcGxhbnQgYWNyb3NzIHR3byBnZW5vdHlwZXMgb2YgcmljZS4KVGhlcmUgYXJlIHRocmVlIHBvdHMgcGVyIGdlbm90eXBlLCBhbmQgdGhyZWUgcGxhbnRzIHBlciBwb3QuIChBbGwgdGhyZWUgcGxhbnRzIGluIGEgcG90IGFyZSB0aGUgc2FtZSBnZW5vdHlwZS4pClRoZW4gSSBjb3VudCB0aGUgbnVtYmVyIG9mIHNlZWRzIGluIGVhY2ggcGxhbnQuXApBbmQgKlRIQVQqIGlzIGEgcmVwZWF0ZWQgbWVhc3VyZS4gVGhlIHBvdHMgYXJlIGJlaW5nIHJlcGVhdGVkbHkgbWVhc3VyZWQgZm9yIHRoZSBwbGFudHMgaW4gdGhlbS4KQW5kIHRoZSBwb3RzIGNhbm5vdCBiZSB1c2VkIGFzIGEgYmxvY2tpbmcgZmFjdG9yLCBiZWNhdXNlIHRoZXJlIGlzIG9ubHkgb25lIGdlbm90eXBlIHBlciBwb3QuCgpCdXQgd2h5IGlzIHRoYXQgYSBwcm9ibGVtPwpSZW1lbWJlciwgdGhlIGFzc3VtcHRpb24gb2YgQU5PVkEgaXMgdGhhdCBlYWNoIG9ic2VydmF0aW9uIGlzIGluZGVwZW5kZW50IG9mIHRoZSBvdGhlci4KQW5kIHJlcGVhdGVkIG1lYXN1cmVzIGlzIGEgdmlvbGF0aW9uIG9mIHRoYXQgYXNzdW1wdGlvbi4KV2hlbiBtdWx0aXBsZSBtZWFzdXJlbWVudHMgb2YgdGhlIHNhbWUgZW50aXR5IHdlcmUgdGFrZW4sCnRob3NlIG1lYXN1cmVtZW50cyB3aWxsIE5PVCBiZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLApiZWNhdXNlIHRoZXkgYXJlIGFsbCBhZmZlY3RlZCBieSB0aGUgc2FtZSBlbnRpdHkuCgpSZXBlYXRlZCBtZWFzdXJlcyBhbHdheXMgcmVkdWNlIHRoZSBudW1iZXIgb2YgaW5kZXBlbmRlbnQgb2JzZXJ2YXRpb25zIHlvdSBoYXZlLAphbmQgb25lIG11c3QgY29ycmVjdCBmb3IgcmVwZWF0ZWQgbWVhc3VyZXMuCgojIFdvcmtpbmcgd2l0aCByZXBlYXRlZCBtZWFzdXJlcyAtIHVzaW5nIHJhbmRvbSBlZmZlY3RzCgpUbyBjb3JyZWN0IGZvciByZXBlYXRlZCBtZWFzdXJlcywgd2UgbmVlZCB0byBkZWNsYXJlIHRoZSBlbnRpdGllcyB0aGF0IGFyZSByZXBlYXRlZGx5IG1lYXN1cmVkIGFzICJyYW5kb20gZWZmZWN0cyIuCgpUaGlzIGlzIGEgdmVyeSBhYnN0cmFjdCBjb25jZXB0LiBTbyB0aGUgYmVzdCB3YXkgdG8gZXhwbGFpbiBpcyB0byB1c2UgYW4gZXhhbXBsZS4KCldlIGFyZSBjb21wYXJpbmcgdGhlIGhlaWdodCBvZiB0d28gcmljZSBnZW5vdHlwZXMsIFdUIGFuZCBtdXRhbnQsIHRocm91Z2ggdGltZS4KRXZlcnkgd2VlayB3ZSBtZWFzdXJlIHRoZSBoZWlnaHRzIG9mIHRob3NlIHBsYW50cy4KKERhdGEgZnJvbSBTdW5kYXJlc2FuIExhYiwgRGVwYXJ0bWVudCBPZiBQbGFudCBCaW9sb2d5LCBVQyBEYXZpcykKCmBgYHtyfQpyaWNlX2dyb3d0aCA8LSByZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pvaG5zaG9ydGVyL1RlYWNoaW5nRGF0YS9yZWZzL2hlYWRzL21haW4vcmljZV9ncm93dGhfZGF0YS5jc3YiKQpoZWFkKHJpY2VfZ3Jvd3RoKQpgYGAKCkluIHRoaXMgZXhwZXJpbWVudCwgZWFjaCBwb3Qgd2FzIHJhbmRvbWx5IGFzc2lnbmVkIGEgZ2Vub3R5cGUsIGVpdGhlciBXVCBvciBtdXRhbnQuIFRoZSBtdXRhbnQgaXMgY2FsbGVkICI0OC80OCIuClRoZXJlIHdhcyBvbmUgcGxhbnQgcGVyIHBvdC4KVGhlIHRvdGFsIG9mIDQ4IHBvdHMgd2VyZSByYW5kb21seSBwbGFjZWQgaW50byA2IGZsYXRzLCBhbmQgOCBwb3RzIHBlciBmbGF0LgpTbyB0aGUgZmxhdCB3YXMgYSBibG9ja2luZyBmYWN0b3IuCldlIG1lYXN1cmUgdGhlIGhlaWdodCBldmVyeSB3ZWVrLCBzdGFydGluZyBmcm9tIHdlZWsgMyB0byB3ZWVrIDksIChidXQgbm90IHdlZWsgOCksIHNvIHRvdGFsIG9mIDYgdGltZSBwb2ludHMuCgpCZWZvcmUgd2UgdGFsayBhYm91dCByYW5kb20gZWZmZWN0cywgd2UgbmVlZCB0byB0YWxrIGFib3V0IGZpeGVkIGVmZmVjdHMuClNpbXBseSBwdXQsIHRoZSBmaXhlZCBlZmZlY3RzIGFyZSB5b3VyIHRyZWF0bWVudHMuCkluIHRoaXMgZXhhbXBsZSwgV2UgaGF2ZSB0d28gZml4ZWQgZWZmZWN0czogZ2Vub3R5cGUgYW5kIGFnZS4KCkxldCdzIGxvb2sgYXQgYWxsIHRoZSBmYWN0b3JzIGluIHRoaXMgZXhwZXJpbWVudAoKfCBzb3VyY2VzIHwgZmFjdG9yIHwgbGV2ZWxzIHwKfDotLS0tLS0tOnw6LS0tLS0tOnw6LS0tLS0tOnwKfCAgdGltZSAgIHwgdHJlYXQgIHwgICA2ICAgIHwKfCAgZ2Vub3QgIHwgdHJlYXQgIHwgICAyICAgIHwKfCAgZmxhdCAgIHwgYmxvY2sgIHwgICA2ICAgIHwKfCAgIHBvdCAgIHwgICpFVSogIHwgICA0OCAgIHwKCkJlY2F1c2UgdGhlcmUgYXJlIHR3byBpbmRlcGVuZGVudCB2YXJpYWJsZXMgKHRpbWUgYW5kIGdlbm90eXBlKSBhbmQgb25lIGJsb2NraW5nIGZhY3RvciwKdGhpcyBleHBlcmltZW50IHdpbGwgYmUgY2FsbGVkIGEgcmFuZG9taXplZCBibG9jayBtdWx0aWZhY3RvcmlhbCBkZXNpZ24uCgoqTm90ZSogSW4gdGhpcyBleGFtcGxlLCBwbGFudCBvciBwb3QgaXMgdGhlIGV4cGVyaW1lbnRhbCB1bml0IGZvciBnZW5vdHlwZSwKYmVjYXVzZSB0aGUgdHJlYXRtZW50IG9mIGdlbm90eXBlIHdhcyBhcHBsaWVkIHRvIGVhY2ggcG90LCBhbmQgdGhlcmUgaXMgb25seSBvbmUgcGxhbnQgaW4gZWFjaCBwb3QuCipOb3RlKiBQb3QgaXMgYWxzbyB0aGUgZW50aXR5IHRoYXQgaGFzIGJlZW4gcmVwZWF0ZWRseSBtZWFzdXJlZCB0aHJvdWdoIHdlZWtzLgoKWW91IG1pZ2h0IGFzaywgdGhlbiB3aGVyZSBpcyB0aGUgb2JzZXJ2YXRpb25hbCB1bml0PwpUaGUgT1UgaXMgYWN0dWFsIHRoZSBwbGFudCBhdCBlYWNoIHdlZWssIG9yIHRoZSBwbGFudDp3ZWVrIGNvbWJpbmF0aW9uLgoKQ29taW5nIGJhY2sgdG8gcmFuZG9tIGVmZmVjdHMuIFdoYXQgaXMgYSByYW5kb20gZWZmZWN0PwoKMS4gIEEgcmFuZG9tIGVmZmVjdCAqQ0FOTk9UKiBiZSBhIHRyZWF0bWVudCAoYmVjYXVzZSB0aGV5IGFyZSBmaXhlZCBlZmZlY3RzKTsKMi4gIEFuIEVVIHRoYXQgaXMgbm90IGFuIE9VIG11c3QgYmUgZGVjbGFyZWQgYXMgYSByYW5kb20gZWZmZWN0OwozLiAgQW4gZW50aXR5IHRoYXQgaXMgcmVwZWF0ZWRseSBtZWFzdXJlZCBtdXN0IGJlIGRlY2xhcmVkIGFzIGEgcmFuZG9tIGVmZmVjdDsKNC4gIEJsb2NraW5nIGZhY3RvcnMgY2FuIGJlIGRlY2xhcmVkIGFzIHJhbmRvbSBlZmZlY3RzLCBidXQgdGhleSBkb24ndCBoYXZlIHRvLgoKU28gaW4gdGhpcyBleGFtcGxlLCB3aGF0IG5lZWRzIHRvIGJlIGRlY2xhcmVkIGFzIGEgcmFuZG9tIGVmZmVjdD8KVGhlIHBvdCBuZWVkcyB0byBiZSBkZWNsYXJlZCBhcyBhIHJhbmRvbSBlZmZlY3QsCnNpbmNlIGl0IGlzIGJvdGggdGhlIEVVIGZvciBnZW5vdHlwZSBhbmQgdGhlIGVudGl0eSBvZiByZXBlYXRlZCBtZWFzdXJlcy4KCiMgU2V0dGluZyB1cCBhIG1peGVkIGVmZmVjdCBtb2RlbAoKQSBtaXhlZCBlZmZlY3QgbW9kZWwgcmVmZXJzIHRvIGEgbW9kZWwgdGhhdCBjb250YWlucyBib3RoIGZpeGVkIGVmZmVjdHMgYW5kIHJhbmRvbSBlZmZlY3RzLgpBIG1peGVkIGVmZmVjdCBtb2RlbCBpcyBhcHByb3ByaWF0ZSBmb3IgdGhpcyBleHBlcmltZW50LApiZWNhdXNlIHdlIGhhdmUgdHdvIGZpeGVkIGVmZmVjdHMgKHRpbWUgYW5kIGdlbm90eXBlKSBhbmQgb25lIHJhbmRvbSBlZmZlY3QgKHBvdCkuCiMjIyMgbm90ZSwgcG90IGlzIHRoZSBjb3ZhcmlhdGUgd2l0aGluIHdoaWNoIHdlIGhhdmUgcmVwZWF0ZWQgbWVhc3VyZXMKCkhvdyBkbyBJIHNldCB1cCB0aGUgbW9kZWw/ClRvIHNldCB1cCB0aGUgbWl4ZWQgZWZmZWN0IG1vZGVsLCB3ZSB3aWxsIG5lZWQgYSBuZXcgZnVuY3Rpb24uCkluc3RlYWQgb2YgYGxtKClgLCB3ZSB3aWxsIHVzZSBgbG1lcigpYC4gVGhpcyB3aWxsIGJlIHRoZSBjb21tYW5kIGZvciBtaXhlZCBlZmZlY3QgbGluZWFyIG1vZGVsLgoKVG8gc3BlY2lmeSBhIHJhbmRvbSBlZmZlY3QsIHdlJ2xsIHVzZSB0aGUgYCgxfHJhbmRvbV9lZmZlY3QpYCBzeW50YXguCkluIHRoaXMgZXhhbXBsZSwgaXQgd2lsbCBiZSBgKDF8cG90KWAKCkluIHRoZSBtb2RlbCwgeW91IHdpbGwgcHV0IGluIHlvdXIgZml4ZWQgZWZmZWN0IGFuZCBpbnRlcmFjdGlvbnMgZmlyc3QsCnRoZW4geW91IHB1dCBpbiBibG9ja2luZyBmYWN0b3JzLAp0aGVuIHlvdSBwdXQgaW4gcmFuZG9tIGVmZmVjdHMuClNvIHRoZSBtb2RlbCB3aWxsIGJlIGBsbWVyKGhlaWdodCB+IHRpbWUgKyBnZW5vdHlwZSArIHRpbWU6Z2Vub3R5cGUgKyBmbGF0ICsgKDF8cG90KSlgCllvdSBjYW4gYWxzbyBkbyBgdGltZSpnZW5vdHlwZSArIGZsYXQgKyAoMXxwb3QpLmAgVGhhdCBnaXZlcyB5b3UgdGhlIHNhbWUgdGhpbmcuCgpEbyBub3QgaW5jbHVkZSB0aGUgaW50ZXJhY3Rpb25zIHdpdGggYmxvY2tpbmcgZmFjdG9ycyAoZmxhdCkuClRoZSBibG9ja2luZyBmYWN0b3Igb25seSBleGlzdHMgdG8gY29udHJvbCBmb3IgdW5pbnRlbmRlZCB2YXJpYXRpb25zLgpBbmQgd2UgYXJlIG5vdCBpbnRlcmVzdGVkIGluIHRoZSBmbGF0OnRpbWUgb3IgZmxhdDpnZW5vdHlwZSBlZmZlY3RzLgoKWW91IG1pZ2h0IGFzayBjYW4gSSBkbyBgaGVpZ2h0IH4gZ2Vub3R5cGUgKiB0aW1lICsgZmxhdCArICgxfHBsYW50KWA/IEluIGFuIGV4cGVyaW1lbnQgbGlrZSB0aGlzLFwKeW91IHNob3VsZCBwdXQgdGhlIG5vbi1tYW5pcHVsYXRpdmUgZmFjdG9yICh0aW1lKSBmaXJzdCxcCnRoZW4geW91IHB1dCB0aGUgbWFuaXB1bGF0aXZlIGZhY3RvciAoZ2Vub3R5cGUpIHNlY29uZC4KClRoZSByZWFzb24gaXMgdGhhdCBpbiBhIG1peGVkIGVmZmVjdCBtb2RlbCwgdGhlIGZpcnN0IGZhY3RvciBpbiB0aGUgbW9kZWwgd2lsbCBhY2NvdW50IGZvciB2YXJpYXRpb24gZmlyc3Q7CnRoZW4gdGhlIHJlc3Qgb2YgdGhlIHZhcmlhdGlvbiB3aWxsIGJlIHBhc3NlZCBvbiB0byB0aGUgc2Vjb25kIGZhY3RvciBpbiB0aGUgbW9kZWwsCmFuZCBzbyBvbi4KCkJ5IGNvbW1vbiBzZW5zZSwgd2Uga25vdyBwbGFudHMgZ3JvdyB0YWxsZXIgb3ZlciB0aW1lLiBTbyB3ZSBleHBlY3QgdGhhdCB0aW1lIGV4cGxhaW5zIG1vcmUgdmFyaWF0aW9uIHRoYW4gZ2Vub3R5cGUuClNvIHdlIHdpbGwgcHV0IHRpbWUgZmlyc3QgaW4gdGhlIG1vZGVsLgoKWW91IGNhbiBhbHNvIGRlY2xhcmUgdGhlIGZsYXQgYXMgYSByYW5kb20gZWZmZWN0IGJ5IHVzaW5nIGAoMXxmbGF0KWAuCkVpdGhlciB3YXkgaXMgY29ycmVjdCwgYnV0IHNldHRpbmcgdGhlIGZsYXQgYXMgYSByYW5kb20gZWZmZWN0IGlzIG1vcmUgY29uc2VydmF0aXZlLAptZWFuaW5nIHlvdSdsbCBuZWVkIGEgbGFyZ2VyIGRpZmZlcmVuY2UgaW4gbWVhbiB0byBkZXRlY3QgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlCgpMYXN0IHRoaW5nOiBiZWZvcmUgeW91IHNldCB1cCB0aGUgbW9kZWwsIGlzIHRoZXJlIGFueSBudW1lcmljIHZhcmlhYmxlcyB0aGF0IHlvdSBuZWVkIHRvIGNoYW5nZSB0byBmYWN0b3JzPwoKYGBge3J9CnJpY2VfZ3Jvd3RoIDwtIHJpY2VfZ3Jvd3RoICU+JSAKICBtdXRhdGUoYWdlLmYgPSBmYWN0b3IoYWdlX3dlZWtzKSkgJT4lIAogIG11dGF0ZShmbGF0LmYgPSBmYWN0b3IoZmxhdCkpIApgYGAKCmBgYHtyfQptb2RlbF9yaWNlIDwtIGxtZXIoSGVpZ2h0X21tIH4gYWdlLmYgKiBnZW5vdHlwZSArICgxfGZsYXQuZikgKyAoMXxwb3QpLCBkYXRhID0gcmljZV9ncm93dGgpCmBgYAoKIyBEYXRhIHZpc3VhbGl6YXRpb24KCkJlZm9yZSB3ZSBkbyBhbnkgYW5hbHlzaXMsIGxldCdzIHBsb3QgdGhlIGRhdGEgYW5kIGxvb2sgYXQgaXQgZmlyc3QuClBsb3QgYWdlLmYgb24geCBheGlzLCBhbmQgSGVpZ2h0X21tIG9uIHkgYXhpcy4gQ29sb3IgYnkgZ2Vub3R5cGUuCgpNYWtlIHRoZSBiZXN0IHBsb3QgeW91IGNhbiBoZXJlOgoKYGBge3J9Cndpc3RlcmlhIDwtIGMoImdyZXk2NSIsICJidXJseXdvb2QzIiwgImtoYWtpMiIsICJwbHVtMSIsICJsaWdodGN5YW4yIiwgImNvcm5mbG93ZXJibHVlIiwgInNsYXRlYmx1ZTMiKQoKcmljZV9ncm93dGggJT4lIAogIGdncGxvdChhZXMoeCA9IGFnZV93ZWVrcywgeSA9IEhlaWdodF9tbSkpICsKICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJsaW5lIiwgIAogICAgICAgICAgICAgICBmdW4gPSBtZWFuLCAgCiAgICAgICAgICAgICAgIGFlcyhncm91cCA9IGdlbm90eXBlLCBjb2xvciA9IGdlbm90eXBlKSwgIAogICAgICAgICAgICAgICBzaXplID0gMS4yKSArIAogIHN0YXRfc3VtbWFyeShnZW9tID0gInJpYmJvbiIsICAgCiAgICAgICAgICAgICAgIGZ1bi5kYXRhID0gbWVhbl9zZSwgCiAgICAgICAgICAgICAgIGFlcyhncm91cCA9IGdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgZmlsbCA9IGdlbm90eXBlKSwgCiAgICAgICAgICAgICAgIGFscGhhID0gMC41KSArICAgCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGdlbm90eXBlKSwgCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjEsIHNlZWQgPSA2NjYpLCAgICAKICAgICAgICAgICAgIGFscGhhID0gMC44LCAgICAgICAgICAgICAKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwgCiAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsgICAgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gd2lzdGVyaWFbYygxLCA3KV0pICsgIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB3aXN0ZXJpYVtjKDEsIDcpXSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygzLCA0LCA1LCA2LCA3LCA5KSkgKyAgCiAgbGFicyh4ID0gIkFnZSAod2Vla3MpIiwgICAgICAgICAgICAgIAogICAgICAgeSA9ICJIZWlnaHQgbW0iLAogICAgICAgZmlsbCA9ICJnZW5vdHlwZSIsCiAgICAgICBjb2xvciA9ICJnZW5vdHlwZSIpICsKICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMSwgbmNvbCA9IDIpKSArICMgc2V0IGZpbGwgbGVnZW5kIHRvIDEgcm93IDIgY29sdW1ucy4gCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuOCwgMC4xNSksCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAxLjIpLCAKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siLCBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiYm9sZCIpCiAgICAgICAgKQoKYGBgCgpXZSBjYW4gYWxzbyBwdWxsIG91dCB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzLgpXZSdsbCBuZWVkIHRvIGdyb3VwIGJ5IGdlbm90eXBlIGFuZCBhZ2UuZgoKYGBge3J9CnJpY2VfZ3Jvd3RoICU+JSAKICBncm91cF9ieShnZW5vdHlwZSwgYWdlLmYpICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oSGVpZ2h0X21tKSwKICAgICAgICAgICAgdmFyID0gdmFyKEhlaWdodF9tbSksCiAgICAgICAgICAgIHNkID0gc2QoSGVpZ2h0X21tKSwKICAgICAgICAgICAgbiA9IG4oKSkgCmBgYAoKVGhlIHZhcmlhbmNlcyBzZWVtIHRvIGluY3JlYXNlIGFzIHRoZSBtZWFucyBpbmNyZWFzZSwgYnV0IEkgZG9uJ3QgdGhpbmsgaXQncyB0b28gYmFkIChub3Qgb3JkZXJzIG9mIG1hZ25pdHVkZSBkaWZmZXJlbnQpLgpJZiB5b3UgYXJlIGludGVyZXN0ZWQsIHlvdSBjYW4gdHJ5IGEgbG9nIHRyYW5zZm9ybWF0aW9uIGFuZCBjb21wYXJlIHJlc3VsdHMuIApJIHRoaW5rIHRoZSBjb25jbHVzaW9ucyBzaG91bGQgcHJhY3RpY2FsbHkgYmUgdGhlIHNhbWUuCgojIFN0YXRzCgpXZSBoYXZlIG91ciBtb2RlbCwgbm93IGxldCdzIGNoZWNrIHRoZSBhc3N1bXB0aW9ucyBvZiBBTk9WQSBmaXJzdC4KCk5vcm1hbGl0eT8KSXQgdHVybnMgb3V0IHRoZSBgcGxvdChtb2RlbCwgd2hpY2ggPSAyKWAgY29tbWFuZCB3b3VsZG4ndCB3b3JrIG9uIG1peGVkIGVmZmVjdCBtb2RlbHMuCldlIHdpbGwgdXNlIGBxcW5vcm0ocmVzaWQobW9kZWwpKWAgaW5zdGVhZC4KVGhlIGByZXNpZCgpYCBmdW5jdGlvbiBwdWxsIG91dCBhbGwgdGhlIHJlc2lkdWVzIGluIGEgbW9kZWwuCgpgYGB7cn0KcXFub3JtKHJlc2lkKG1vZGVsX3JpY2UpKQpgYGAKClByZXR0eSBub3JtYWxseSBkaXN0cmlidXRlZC4KCkVxdWFsIHZhcmlhbmNlIGFjcm9zcyBncm91cHM/CgpgYGB7cn0KcGxvdChtb2RlbF9yaWNlKQpgYGAKCkl0IHR1cm5zIG91dCB3aGVuIHlvdSBjYWxsIGBwbG90KClgIG9uIGEgbWl4ZWQgZWZmZWN0IG1vZGVsLCBpdCBnaXZlcyB5b3UgdGhlIHJlc2lkdWUgdnMuIG1lYW4gcGxvdC4KVGhlIHJlc2lkdWVzIHNlZW0gdG8gYmUgcHJldHR5IGV2ZW5seSBzcHJlYWQgYWNyb3NzIHRoZSByYW5nZSBvZiBtZWFuLgpUaGUgdmFyaWFuY2VzIGFyZSBtb3JlIG9yIGxlc3MgZXZlbiBhY3Jvc3MgZ3JvdXBzLCBhbHRob3VnaCB0aGVyZSBpcyBhIHNsaWdodGx5IGxhcmdlciBzcHJlYWQgYXQgdGhlIGhpZ2ggZW5kIG9mIHRoZSBkYXRhLgoKU28gbm93IHdlIGFyZSBhbGwgY2xlYXIgdG8gZG8gQU5PVkEuCgojIyBBTk9WQQoKYGBge3J9CmFub3ZhKG1vZGVsX3JpY2UpCmBgYAoKTm90IHN1cnByaXNpbmdseSwgYWdlLmYgZXhwbGFpbiB0aGUgbW9zdCB2YXJpYXRpb24gaW4gdGhlIGRhdGEgKEYgPSA0NTc4KSEKR2Vub3R5cGUgYWxzbyBleHBsYWlucyBhIHNpZ25pZmljYW50IGFtb3VudCBvZiB2YXJpYXRpb24gaW4gdGhlIGRhdGFzZXQgKEYgPSAyMyA+PiAxKS4KVGhlIGludGVyYWN0aW9uIGJldHdlZW4gdGhlIHRyZWF0bWVudHMgYXJlIGFsc28gc2lnbmlmaWNhbnQgKEYgPSA1ID4gMSkuCgojIyBUdWtleSB0ZXN0CgpMZXQncyByZWFsbHkgbm90IGEgcXVlc3Rpb24gb2Ygd2hldGhlciBvciBub3QgdGhlIGhlaWdodCBpcyBkaWZmZXJlbnQgYWNyb3NzIGFnZSwKYmVjYXVzZSB3ZSBrbm93IHBsYW50cyBncm93IHRhbGxlciBvdmVyIHRpbWUuClRoZSByZWFsIHF1ZXN0aW9uIGlzIHdoZXRoZXIgb3Igbm90IFdUIGlzIHRhbGxlciBvciBzaG9ydGVyIHRoYW4gdGhlIG11dGFudCBhY3Jvc3MgYWdlLgoKU28gdGhlIGBlbW1lYW5zYCBsYXlvdXQgc2hvdWxkIGJlIGB+IGdlbm90eXBlIHwgYWdlLmZgCgpgYGB7cn0KZXN0aW1hdGVfcmljZSA8LSBlbW1lYW5zKG1vZGVsX3JpY2UsIHBhaXJ3aXNlIH4gZ2Vub3R5cGUgfCBhZ2UuZikKZXN0aW1hdGVfcmljZSRjb250cmFzdApgYGAKCllvdSBjYW4gYWxzbyBsb29rIGF0IGNsZCBpZiB5b3UgbGlrZS4KCmBgYHtyfQpjbGQoZXN0aW1hdGVfcmljZSRlbW1lYW5zLCBMZXR0ZXJzID0gbGV0dGVycykKYGBgCgpXaGF0IGRvZXMgdGhpcyB0ZWxsIHVzPwpJdCB0ZWxscyB1cyB0aGF0IGluIGVhY2ggdGltZSBwb2ludCAoZXhjZXB0IHRoZSBmaXJzdCksCldUIHBsYW50cyBhcmUgb24gYXZlcmFnZSBzaWduaWZpY2FudGx5IHRhbGxlciB0aGFuIDQ4LzQ4IHBsYW50cy4KCihOb3RlOiBUaGUgZGlmZmVyZW5jZXMgaW4gaGVpZ2h0cyBhdCB3ZWVrIDkgaXMgMjguMyBtbS4KSW4gcmVhbGl0eSwgfjMwIG1tICgzY20pIGRpZmZlcmVuY2UgaW4gaGVpZ2h0IGlzIHByYWN0aWNhbGx5IG5vdGhpbmcgZm9yIHJpY2UgcGxhbnRzLgpFdmVuIHRob3VnaCBzb21ldGhpbmcgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgaXQgZG9lcyBub3QgYWx3YXlzIG1lYW4gc29tZXRoaW5nIHByYWN0aWNhbGx5IGRpZmZlcmVudC4pCgojIEV4ZXJjaXNlCgpOb3cgeW91IGhhdmUgbGVhcm5lZCBob3cgdG8gZGVhbCB3aXRoIHJlcGVhdGVkIG1lYXN1cmVzIGluIGFuIGV4cGVyaW1lbnQsCml0J3MgdGltZSBmb3IgeW91IHRvIHByYWN0aWNlLgoKV2Ugd2lsbCB1c2UgYSBtaW50IGdyb3d0aCBleHBlcmltZW50IGFzIGFuIGV4YW1wbGUuCkluIHRoaXMgZXhwZXJpbWVudCwgdGhlIHJlc2VhcmNoZXJzIGxvb2tlZCBhdCB0aGUgZWZmZWN0IG9mIDYgdHJlYXRtZW50cyAoQSAtIEYpIG9uIG1pbnQgZ3Jvd3RoLgpFYWNoIHRyZWF0bWVudCBoYXMgMyBwb3RzLgpFYWNoIHBvdCBoYXMgNCBwbGFudHMuIFRoZSB0cmVhdG1lbnQgd2FzIGFwcGxpZWQgdG8gdGhlIHBvdCwgbm90IHRoZSBpbmRpdmlkdWFsIHBsYW50cy4KVGhlIGdyb3d0aCBvZiBlYWNoIHBsYW50IGluIGVhY2ggcG90IHdhcyBtZWFzdXJlZC4KKERhdGEgZnJvbSBVQyBEYXZpcyBQbGFudCBTY2llbmNlcyBjb3Vyc2UgUExTMjA1LCBXaW50ZXIgMjAxNykKCmBgYHtyfQptaW50X2RhdGEgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9qb2huc2hvcnRlci9UZWFjaGluZ0RhdGEvcmVmcy9oZWFkcy9tYWluL01pbnQuY3N2IikKaGVhZChtaW50X2RhdGEpCnRhaWwobWludF9kYXRhKQoKYGBgCgpUaGVyZSBpcyBhIHByb2JsZW0gd2l0aCBob3cgdGhlIGRhdGEgd2VyZSByZWNvcmRlZC4gTWF5YmUgaXQncyBub3Qgb2J2aW91cyB0byB5b3UuCkluIGVhY2ggdHJlYXRtZW50LCB0aGUgbmFtZSBvZiB0aGUgUG90IGlzIGFsbCBQb3RfMSwgUG90XzIgYW5kIFBvdF8zLgpIb3dldmVyLCBpbiB0aGUgYWN0dWFsIGV4cGVyaW1lbnQsIFBvdF8xIGZyb20gVHJlYXRtZW50IEEgaXMgbm90IHRoZSBzYW1lIFBvdF8xIGZvciBUcmVhdG1lbnQgQiwgb3IgQ0RFRi4KVGhlIHNhbWUgYXBwbGllcyB0byBQb3RfMiBhbmQgUG90XzMuClNpbXBseSBwdXQsIHRoZSBwb3RzIGluIGVhY2ggdHJlYXRtZW50IG5lZWQgdG8gaGF2ZSB0aGVpciBvd24gdW5pcXVlIGlkZW50aWZpZXIuCkxldCdzIGZpeCB0aGF0IGZpcnN0LgoKYGBge3J9Cm1pbnRfZGF0YSA8LSBtaW50X2RhdGEgJT4lIAogIG11dGF0ZShQb3QuSUQgPSBwYXN0ZShQb3QsIFRydG10KSkKCmhlYWQobWludF9kYXRhKQptaW50X2RhdGEgJT4lIAogIGdyb3VwX2J5KFRydG10KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKEdyb3d0aCksCiAgICAgICAgICAgIHZhciA9IHZhcihHcm93dGgpLAogICAgICAgICAgICBzZCA9IHNkKEdyb3d0aCksCiAgICAgICAgICAgIG4gPSBuKCkpIApgYGAKCk5vdyBlYWNoIHBvdCBoYXMgdGhlaXIgb3duIHVuaXF1ZSBJRC4KUG90IGlzIHRoZSBFVSB0aGF0IGhhcyBtdWx0aXBsZSBtZWFzdXJlbWVudHMuCgojIyBWaXN1YWxpemF0aW9uCgpNYWtlIHRoZSBiZXN0IHBsb3QgeW91IGNhbiB0byB2aXN1YWxpemUgdGhlIGRhdGEuCgpXaGF0IHRvIHB1dCBvbiB4IGF4aXM/IFdoYXQgdG8gY29sb3IvZmlsbCB3aXRoPyBBbnkgZmFjZXRpbmcgdGhhdCB5b3Ugd2FudCB0byB1c2U/CgpNYWtlIHlvdXIgcGxvdCBoZXJlOgoKYGBge3J9Cm1pbnRfZGF0YSAlPiUgCiAgbXV0YXRlKFBsYW50ID0gZmFjdG9yKFBsYW50KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IFRydG10LCB5ID0gR3Jvd3RoKSkgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBQbGFudCksIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4xLCBzZWVkID0gNjY2KSwgICAgCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCwgICAgICAgICAgICAgCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIHNoYXBlID0gMjEsIAogICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArICAgIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdpc3RlcmlhW2MoMSwyLDMsIDcpXSkgKyAgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdpc3RlcmlhW2MoMSwyLDMsIDcpXSkgKyAKICAjc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMywgNCwgNSwgNiwgNywgOSkpICsgIAogIGxhYnMoeCA9ICJUcmVhdG1lbnQiLCAgICAgICAgICAgICAgCiAgICAgICB5ID0gIkdyb3d0aCIsCiAgICAgICBmaWxsID0gIlBsYW50IiwKICAgICAgIGNvbG9yID0gIlBsYW50IikgKwogIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogICNndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMSwgbmNvbCA9IDIpKSArICMgc2V0IGZpbGwgbGVnZW5kIHRvIDEgcm93IDIgY29sdW1ucy4gCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDEuMiksIAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImJsYWNrIiwgZmFjZSA9ICJib2xkIikKICAgICAgICApCmBgYAoKIyMgV2hhdCBpcyBiZWluZyByZXBlYXRlZGx5IG1lYXN1cmVkIGluIHRoaXMgZXhwZXJpbWVudD8KCkNhbiB5b3UgdGVsbCB3aGljaCBlbnRpdHkgd2FzIHJlcGVhdGFibHkgbWVhc3VyZWQ/CgpGaWxsIGluIHRoZSB0YWJsZSBhbmQgd3JpdGUgZG93biB0aGUgbW9kZWwuCldoYXQgYXJlIHRoZSBzb3VyY2VzIG9mIHZhcmlhdGlvbj8KV2hhdCBmYWN0b3JzIGFyZSB0aGV5PyAodHJlYXRtZW50PyBibG9jaz8gb2JzZXJ2YXRpb25hbCB1bml0cz8gZXhwZXJpbWVudGFsIHVuaXRzPykKSG93IG1hbnkgbGV2ZWxzIGluIGVhY2g/CgoKV2hhdCBpcyB0aGUgZXhwZXJpbWVudGFsIHVuaXQgZm9yIHRyZWF0bWVudD8KV2hhdCBpcyB0aGUgb2JzZXJ2YXRpb25hbCB1bml0PwoKfCBzb3VyY2VzIHwgZmFjdG9yIHwgbGV2ZWxzIHwKfDotLS0tLS0tOnw6LS0tLS0tOnw6LS0tLS0tOnwKfCAgVHJtdCAgIHwgdHJlYXQgIHwgICA2ICAgIHwKfCBQb3QuSUQgIHwgICpFVSogIHwgICAxOCAgIHwKfCBQb3QuSUQuUGxhbnQgfCAqT1UqIHwgNzIgfAoKVGVjaG5pY2FsbHkgcGxhbnQgY291bGQgYmUgYSBibG9ja2luZyBmYWN0b3IgaWYgdGhlcmUgd2FzIHNvbWV0aGluZyBzeXN0ZW1hdGljIGFib3V0IGl0IGUuZy4gY29taW5nIGZyb20gYSBjZXJ0YWluIHNlZWQgY29udGFpbmVyIG9yIHdoYXRldmVyLCBidXQgaW4gdGhpcyB3ZSBrbm93IG5vdGhpbmcsIGl0J3MganVzdCBhIG51bWJlciwgYW5kIGRvZXNuJ3Qgc2VlbSB0byBhZmZlY3QgdGhlIHRyZWF0bWVudHMgZnJvbSB2aXN1YWxpemluZyB0aGUgZGF0YS4KClNldCB1cCB0aGUgbGluZWFyIG1vZGVsLgoKIyMgQ2hlY2sgYXNzdW1wdGlvbnMgb2YgQU5PVkEKCmBgYHtyfQptb2RlbF9taW50IDwtIGxtZXIoR3Jvd3RoIH4gVHJ0bXQgKyAoMXxQb3QuSUQpLCBkYXRhID0gbWludF9kYXRhKSAjIHJhbmRvbSBpbnRlcmNlcHQgZm9yIFBvdC5JRApxcW5vcm0ocmVzaWQobW9kZWxfcmljZSkpCnBsb3QobW9kZWxfbWludCkKYGBgCgpOb3JtYWxpdHk/CgpFcXVhbCB2YXJpYW5jZT8KCiMjIFJ1biBBTk9WQQoKSG93IHdvdWxkIHlvdSBpbnRlcnByZXQgdGhlIEFOT1ZBIHRhYmxlPwoKYGBge3J9CmFub3ZhKG1vZGVsX21pbnQpCmBgYApGIHZhbHVlIHNpZ25pZmljYW50LCBtZWFucyBvZiB0cmVhdG1lbnQgZ3JvdXBzIGFyZSBkaWZmZXJlbnQuCgojIyBUdWtleSB0ZXN0CgpQdWxsIG91dCB0aGUgY2xkIG91dHB1dCBhbmQgaW50ZXJwcmV0IHRoZSByZXN1bHRzLgoKYGBge3J9CmVzdGltYXRlX21pbnQgPC0gZW1tZWFucyhtb2RlbF9taW50LCBwYWlyd2lzZSB+IFRydG10KQplc3RpbWF0ZV9taW50JGNvbnRyYXN0CmBgYAoKYGBge3J9CmNsZChlc3RpbWF0ZV9taW50LCBMZXR0ZXJzID0gbGV0dGVycykKYGBgCgpUcmVhdG1lbnQgRiBoYXMgdGhlIGhpZ2hlc3QgZXN0aW1hdGUgYnV0IGlzIG5vdCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIEUgYW5kIEQKCiMjIFdoYXQgdG8gc3VibWl0IHRvIE1vb2RsZSAoUGFzcy9GYWlsKQoKRm9yIHRoaXMgbGVzc29uLCBjb21wbGV0ZSB0aGUgZXhlcmNpc2VzICoqaW4geW91ciBzaGFyZWQgRXhlcmNpc2UgUGFjayoqICh0aGUgZmlsZSBgRXhlcmNpc2VfUGFja19UZW1wbGF0ZS5SbWRgKS4KVGhlbiAqKktuaXQgdG8gSFRNTCoqIGFuZCB1cGxvYWQgdGhlIEhUTUwgZmlsZSB0byB0aGUgTW9vZGxlIGV4ZXJjaXNlIGZvbGRlci4KCioqRmlsZSBuYW1lIGZvcm1hdDoqKiBgTGFzdG5hbWVfRmlyc3RuYW1lX0wxMS5odG1sYAoKIyMjIFNhdGlzZmFjdG9yeSAvIE5vdCBzYXRpc2ZhY3RvcnkgKHdoYXQgSSBjaGVjaykKCllvdXIgc3VibWlzc2lvbiBpcyAqKlNhdGlzZmFjdG9yeSoqIGlmOgoKLSBJdCAqKmtuaXRzKiogKEhUTUwgb3BlbnMgYW5kIHNob3dzIHlvdXIgd29yaykuCi0gWW91IGluY2x1ZGVkICoqb3V0cHV0cyoqIChwbG90cy90YWJsZXMvbW9kZWwgb3V0cHV0KSB0aGF0IG1hdGNoIHRoZSBsZXNzb24uCi0gWW91IGFuc3dlcmVkIHRoZSAqKlNlbGYtY2hlY2sgY2hlY2tsaXN0KiogKHNob3J0LCBob25lc3QsIGFuZCBjb21wbGV0ZSkuCi0gWW91ciB3b3JrIGlzICoqcGxhdXNpYmxlKiogKHJpZ2h0IG1ldGhvZCBmb3IgdGhlIGxlc3NvbiwgY29ycmVjdCB2YXJpYWJsZXMsIG5vIG9idmlvdXMgY29weS9wYXN0ZSB3aXRob3V0IHJlc3VsdHMpLgoKSWYgb25lIG9yIG1vcmUgb2YgdGhlc2UgYXJlIG1pc3NpbmcsIGl0IGlzICoqTm90IHNhdGlzZmFjdG9yeSoqIChhbmQgeW91IHJlc3VibWl0KS4KIyMgQWRkaXRpb25hbCBleGVyY2lzZXMgKGNvbXBsZXRlIHRoZXNlIGluIHlvdXIgRXhlcmNpc2UgUGFjaykKCiMjIyBFeGVyY2lzZSAyIOKAlCBSYW5kb20gaW50ZXJjZXB0IG1vZGVsCkZpdCBhIG1peGVkIG1vZGVsIHdpdGggYSByYW5kb20gaW50ZXJjZXB0IGZvciBzdWJqZWN0IChvciByZXBlYXRlZCB1bml0KS4KQ29tcGFyZSBpdCB0byBhIG1vZGVsIHdpdGhvdXQgdGhlIHJhbmRvbSBlZmZlY3QuCgpgYGB7cn0KYXZnX21pbnQgPC0gbWludF9kYXRhICU+JSBzcGxpdChtaW50X2RhdGEkUG90LklEKSAlPiUgbGFwcGx5KGZ1bmN0aW9uKHgpewogIGF2Zy5ncm93dGggPC0gbWVhbih4JEdyb3d0aCkKICB1bmlxdWUudmFycyA8LSB4ICU+JSBkcGx5cjo6c2VsZWN0KGMoVHJ0bXQsIFBvdC5JRCkpICU+JSB1bmlxdWUoKQogIHVuaXF1ZS52YXJzICU8PiUgbXV0YXRlKGF2Z19ncm93dGggPSBhdmcuZ3Jvd3RoKQogIHJldHVybih1bmlxdWUudmFycykKfSkgJT4lIGJpbmRfcm93cygpCgptb2RlbF9taW50X2F2ZyA8LSBsbShhdmdfZ3Jvd3RoIH4gVHJ0bXQsIGRhdGEgPSBhdmdfbWludCkKcGxvdChtb2RlbF9taW50X2F2ZykKYGBgCgoKYGBge3J9CmFub3ZhKG1vZGVsX21pbnRfYXZnKQpgYGAKCmBgYHtyfQplc3RpbWF0ZV9taW50X2F2ZyA8LSBlbW1lYW5zKG1vZGVsX21pbnRfYXZnLCBwYWlyd2lzZSB+IFRydG10KQplc3RpbWF0ZV9taW50X2F2ZyRjb250cmFzdApjbGQoZXN0aW1hdGVfbWludF9hdmcsIExldHRlcnMgPSBsZXR0ZXJzKQpgYGAKCkludGVyZXN0aW5nbHkgd2UgZ2V0IHRoZSBleGFjdCBzYW1lIHJlc3VsdHMuIEl0IHR1cm5zIG91dCB0aGF0IHdpdGggYSBiYWxhbmNlZCBkYXRhc2V0IHRoZSBtaXhlZCBtb2RlbCByZWR1Y2VzIHRvIGF2ZXJhZ2luZyBieSB0aGUgcmVwZWF0ZWQgbWVhc3VyZW1lbnQgY292YXJpYXRlcy4KCioqU2VsZi1jaGVjazoqKiB5b3Ugc2hvdyBib3RoIG1vZGVscyBhbmQgYSBzaG9ydCBqdXN0aWZpY2F0aW9uIGZvciB0aGUgcmFuZG9tIGVmZmVjdC4KCiMjIyBFeGVyY2lzZSAzIOKAlCBUcmFqZWN0b3J5IHBsb3QKTWFrZSBhIHBsb3Qgc2hvd2luZyByZXBlYXRlZCBtZWFzdXJlbWVudHMgb3ZlciB0aW1lIChvciBjb25kaXRpb24pIHBlciBzdWJqZWN0LgoKKipTZWxmLWNoZWNrOioqIGVhY2ggc3ViamVjdCBoYXMgbXVsdGlwbGUgcG9pbnRzOyBwYXR0ZXJucyBhcmUgdmlzaWJsZS4KCiMjIyBFeGVyY2lzZSA0IOKAlCBBc3N1bXB0aW9ucyBhbmQgcmVzaWR1YWxzCkNoZWNrIHJlc2lkdWFsIGRpYWdub3N0aWNzIGZvciB0aGUgbWl4ZWQgbW9kZWwgYW5kIHN0YXRlIG9uZSBsaW1pdGF0aW9uLgoKKipTZWxmLWNoZWNrOioqIGF0IGxlYXN0IG9uZSBkaWFnbm9zdGljIHBsb3QgKyBvbmUgbGltaXRhdGlvbiBzdGF0ZW1lbnQuCgojIyMgRXhlcmNpc2UgNSDigJQgTWluaS10cmFuc2ZlcgpBcHBseSBhIG1peGVkIG1vZGVsIGlkZWEgdG8gYSBkaWZmZXJlbnQgZGF0YXNldCAoYnVpbHQtaW4gb3IgZnJvbSB0aGUgbGVzc29uKSB3aXRoIGEgc2Vuc2libGUgcmFuZG9tIGVmZmVjdC4KCioqU2VsZi1jaGVjazoqKiB5b3UgY2xlYXJseSBpZGVudGlmeSB3aGF0IGlzIHRoZSByZXBlYXRlZC9jbHVzdGVyZWQgdW5pdC4K